#include <stdio.h>

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

// 这里懒得再把单链表的代码打出来了,反正来讲是怎么实现的
// 简单来说,我们只是想要把带有向删除数据的节点从单链表里面删除就行了
// 也就是说,可以理解为:将带有目标数据的节点的前后节点连接,忽略目标节点就行了,最后返回更新后节点的链表
// 所以,我们可以定义phead,ptail,pcur这三个节点指针完成
// phead记录链表的头节点,ptail和pcur负责遍历和重新连接节点
// pcur遍历每一个节点,每次遍历ptail就负责连接pcur排查过的节点
// 当出现了目标节点的时候,pcur就忽略该节点然后继续遍历

typedef struct ListNode ListNode ;

struct ListNode* removeElements(struct ListNode* head, int val) 
{

    ListNode* phead , *ptail ;

    phead = ptail = NULL ; // 需要初始化,不然就会非法访问内存

    ListNode* pcur = head ;

    while (pcur) // 设置循环遍历链表
    {

        if (pcur -> val != val) // 当该节点不满足目标时候,连接节点 否则不连接,略过节点
        {

            if (phead == NULL) // 这里未设置头节点的原因是: 有时候目标节点可能在第一个节点,让pcur排查出第一个不是目标的节点才作头节点
            {

                phead = ptail = pcur ; // 以当前节点作为头结点进行连接

            }

            else // 当有头结点的情况,这时候ptail负责连接"新链表"并往后记录
            {

                ptail -> next = pcur ;

                ptail = ptail -> next ;
                 
            }

        }

        pcur = pcur -> next ;

    }

    if (ptail) // 怕ptail在循环完目标节点后尾部没指向空(防止目标节点在尾部)
    {

        ptail -> next = NULL ;

    }

    return phead ;
    
}